import axios from "axios";
import { redis, Check } from "@/utils";

async function postStableToken() {
   const { data } = await axios.post<Access>("https://api.weixin.qq.com/cgi-bin/stable_token", {
      grant_type: "client_credential",
      appid: process.env.APPID,
      secret: process.env.APPSECRET
   });
   // 设置失效时间
   data.expiration_time = Math.floor(new Date().valueOf() / 1000) + data.expires_in - 100;

   await redis.set("access", JSON.stringify(data));
}

export const getAccessToken = async (err = false) => {
   if (global.getAccessTokenStatus) return;

   // 正在请求
   global.getAccessTokenStatus = true;

   // 从 redis 中读取数据
   let access = await redis.get("access");

   try {
      if (!access) {
         /** 请求微信接口，获取相关信息 */

         await postStableToken();
      } else {
         // 当存在 access 时
         // 获取当前时间
         const date = Math.floor(new Date().valueOf() / 1000);
         const data = JSON.parse(access) as Access;

         // 若当前时间大于失效时间, 重新请求
         if (date > data.expiration_time) getAccessToken();
         if (err) await postStableToken();
      }
   } catch (error) {
      console.log("error", error);
      // 如果请求出错，清空当前数据，并每隔十秒重新请求
      // 检测当前 access 有效性, 无效则 10 秒后请求
      if (!Check.StringIsJSON(access)) setTimeout(getAccessToken, 10000);

      const date = Math.floor(new Date().valueOf() / 1000);
      const data = JSON.parse(access as string) as Access;

      // 若当前时间大于失效时间, 重新请求
      if (date > data.expiration_time) getAccessToken();
   }

   global.getAccessTokenStatus = false;
};

getAccessToken();

redis.get("access").then(res => {
   if (res) {
      if (!Check.StringIsJSON(res)) getAccessToken();

      const access = JSON.parse(res as string) as Access;

      // 首次有效期结束后，设置定时任务
      setTimeout(
         () => {
            // 定时任务，运行期间，有效期结束前重新获取
            setInterval(getAccessToken, (access.expires_in - 100) * 1000);
         },
         (access.expires_in ? access.expires_in : 5000) * 1000
      );
   } else {
      getAccessToken();
   }
});
